package Study2;


import java.util.Arrays;

/**
 * 初始泛型
 *
 */

class MyArrayList<T> {
    public T[] elem; // 泛型数组
    public int size;

    public MyArrayList() {  // 构造方法
//         this.elem = new T[10] ; // 泛型不可以实例化
        this.elem = (T[])new Object[10];   // Object父类 类型强转为 T[]泛型数组

    }

    public T[] getElem(int i) {
        return (T[]) elem[i];  // 需要强转为一下 [T]泛型，因为返回的值是泛型
    }
    public T[] getElem2() {
        return elem;
    }


    public void add(T val) {    // 传参为泛类型
        this.elem[this.size] = val;
        size ++;
    }

}


/*
泛型只是一个占位符，表示当前类是一个泛型类
可以自动进行类型的检查
可以自动进行类型的转换
<>尖括号是泛型的标志
E是类型变量(Type Variable),变量名一般为大写 ，E在定义时是形参，代表的意思是 MYArrayLIst 最终传入单独类型
泛型是为了解决某些容器，算法等代码的通用性而引入，并且能在编译间做类型检查
泛型利用的是Object 是所有类的祖先类，并且父类的引用可以指向子类对象的特定而工作的
 */

/*
泛型的坑
1. this.elem = new T[10] ; // 泛型不可以实例化,而是通过类型强转  this.elem = (T[])new Object[10];
2.   MyArrayList<int> myArrayList = new MyArrayList<>();  // 泛型中简单类型不能作为泛型参数
 */

/*
面试题：泛型到底是怎么编译的
   4: invokespecial #3                  // Method Study2/MyArrayList."<init>":()V
面试官想知道的即使就是4个字，：擦除机制
重要：泛型只是编译时期的一种机制；异常，
擦除机制：在运行的时候，不存在泛型的说法
所有的处理均在编译阶段已经处理了
擦除机制：在编译的时候，泛型类型被擦除为了Object使用，注意不是替换，而是擦除，这两种概念是不同的

 */
public class Study28 {
    public static void main(String[] args) {
        //    MyArrayList<int> myArrayList = new MyArrayList<>();  // 泛型中简单类型不能作为泛型参数
//        MyArrayList<Integer> myArrayList = new MyArrayList<Integer>(); // 等号右边的可以省略不写的
        MyArrayList<Integer> myArrayList = new MyArrayList<>();
        myArrayList.add(9);
//        myArrayList.add("hll"); // 泛型有自动检查时机制

        myArrayList.add(99);
        System.out.println(Arrays.toString(myArrayList.getElem2()));

        MyArrayList<String> myArrayList1 = new MyArrayList<>();
        myArrayList1.add("你好");
        myArrayList1.add("世界");
        System.out.println(Arrays.toString(myArrayList1.getElem2()));


    }


}
